package _02_第二季._01_排序;

import _02_第二季._01_排序.tools.Student;

import java.text.DecimalFormat;

public abstract class Sort<E extends Comparable<E>> implements Comparable<Sort<E>> {
    protected E[] array; //待排序的数组
    private int cmpCount; //比较次数
    private int swapCount; //交换次数
    private long time; //记录执行时间
    //格式转换
    private DecimalFormat fmt = new DecimalFormat("#.00"); //保留两位小数

    public void sort(E[] array){
        if(array == null || array.length < 2) return;

        this.array = array;
        long begin = System.currentTimeMillis();
        sort();
        time = System.currentTimeMillis()-begin;
    }

    protected abstract void sort(); //交给子类去实现的排序方法

    //比较两个索引的方法
    public int cmp(int i1,int i2){
        cmpCount++;
        return array[i1].compareTo(array[i2]);
    }

    //比较数组两个元素大小
    public int cmp(E v1,E v2){
        cmpCount++;
        return v1.compareTo(v2);
    }

    //交换的方法
    public void swap(int i1,int i2){
        swapCount++;
        E tmp = array[i1];
        array[i1] = array[i2];
        array[i2] = tmp;
    }

    @Override
    public int compareTo(Sort o) {
        int result = (int)(time - o.time);
        if (result != 0) return result;

        result = cmpCount - o.cmpCount;
        if (result != 0) return result;

        return swapCount - o.swapCount;
    }

    //转换
    private String numberString(int number) {
        if (number < 10000) return "" + number;

        if (number < 100000000) return fmt.format(number / 10000.0) + "万";
        return fmt.format(number / 100000000.0) + "亿";
    }

    //判断该算法是否具有稳定性
    private boolean isStable(){
        /*if(this instanceof RadixSort09) return true;*/
        if(this instanceof  CountingSort08) return true;
        if(this instanceof ShellSort07) return false;

        Student[] students = new Student[20];
        for (int i = 0; i < students.length; i++) {
            //对每个学生进行初始化,排序之前相邻两个学生的分差10
            students[i] = new Student(i*10,10);
        }
        sort((E[]) students); //对学生数组进行排序

        //排完序再看是否还是相邻两个学生的分差10
        for (int i = 1; i < students.length; i++) {
            int score = students[i].scope;
            int prevScore = students[i-1].scope;
            if(score != prevScore +10) return false;
        }
        return true;
    }

    @Override
    public String toString() {
        String timeStr = "耗时：" + (time / 1000.0) + "s(" + time + "ms)";
        String compareCountStr = "比较：" + numberString(cmpCount);
        String swapCountStr = "交换：" + numberString(swapCount);
        String stableStr = "稳定性: "+ isStable();
        return "【" + getClass().getSimpleName() + "】\n"
                + stableStr + " \t"
                + timeStr + " \t"
                + compareCountStr + "\t "
                + swapCountStr + "\n"
                + "------------------------------------------------------------------";

    }
}
